package cbsc.cha4;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Random;

import cbsc.cha3.AdditionOperation;
import cbsc.cha3.BinaryOperation_3_2;
import cbsc.cha3.Exercise_3_2_3;
import cbsc.cha3.SubstractOperation;

public class BinaryOperationBase {
	static final int UPPER = 20;
	static final int LOWER = 0;
	private BinaryOperation_3_2[][] addbase;
	private BinaryOperation_3_2[][] subbase;
	private BinaryOperation_3_2[][] bopbase;
	
	public BinaryOperation_3_2[][] getAdditionBase() {
		return addbase;
	}
	public BinaryOperation_3_2[][] getSubstractBase() {
		return subbase;
	}
	public BinaryOperation_3_2[][] getOperationBase() {
		return bopbase;
	}
	BinaryOperationBase(){
		produceAdditionBase();
		produceSubstractBase();
		// 先完成加减法算式基，才能构造混合算式基
		produceBinaryOperationBase();
	}
	private void produceAdditionBase(){
		addbase = new AdditionOperation[UPPER+1][UPPER+1]; 
		AdditionOperation ao;
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i+j<=UPPER){
					ao = new AdditionOperation();
					ao.unsafeConstructor(i,j, i+j, '+');
					addbase[i][j]=ao;
				}
			}
		}
	}
	// 左下角的减法三角形， i-j
	private void produceSubstractBase(){
		subbase = new SubstractOperation[UPPER+1][UPPER+1]; 
		SubstractOperation so;
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i >= j){
					so = new SubstractOperation();
					so.unsafeConstructor(i,j,i-j, '-');
					subbase[i][j]=so;
				}
			}
		}
	}
	
	private void produceBinaryOperationBase(){
		bopbase = new BinaryOperation_3_2[UPPER+1][UPPER+1]; 
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){  // 左上角，是加法算式
				if (i+j<=UPPER){
					bopbase[i][j] = addbase[i][j];
				}else {                    // 左下角，是减法算式，转成右下角的
					// 减法的算式变成：0≤i, j≤UPPER and 0≤i(UPPER-j)≤UPPER，
					bopbase[i][j] = subbase[i][UPPER-j];
					// System.out.println("------["+i+","+j+"] ="+bopbase[i][j]);
				}
			}
		}
	}
	private Exercise_3_2_3 generateExercise(int count,BinaryOperation_3_2[][] base){
		//当心：没有检查count的范围！可能引起异常，0 < count 且不能超过算式基中算式的总数
		// 混合算式的数量：(UPPER+1)*(UPPER+1)
		BinaryOperation_3_2 anOperation;
		Exercise_3_2_3 anExercise = new Exercise_3_2_3();	
		Random random = new Random();
		int row, column;	
		while (count > 0 ){								
			do {
				row = random.nextInt(UPPER+1);	
				column = random.nextInt(UPPER+1);
				anOperation = base[row][column];
			} while (anOperation == null || anExercise.contains(anOperation));
			anExercise.add(anOperation);
			// System.out.println(""+ anExercise.length()+"\t"+anOperation.fullString());
			count--;
		}
		return anExercise;
	}
	public Exercise_3_2_3 generateAdditionExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		return generateExercise(operationCount,addbase);	
	}
	public Exercise_3_2_3 generateSubstractExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		return generateExercise(operationCount,subbase);	
	}
	// 把加法基于减法基合并在一个二维数组OperationBase时，使用此方法。
	public Exercise_3_2_3 generateExercise( int operationCount){
		//当心：没有检查operationCount的范围！可能引起异常	
		return generateExercise(operationCount,bopbase);	
	}
	// 为了测试构造的矩阵，屏幕显示
	public void displayFullBase(BinaryOperation_3_2[][] base){
		for (BinaryOperation_3_2[] row: base){
			for (BinaryOperation_3_2 operation:row){
				if (operation != null ){
					System.out.print(operation.fullString()+"\t");
				}
			}
			System.out.println();
		}
	}
	public void displayBase(BinaryOperation_3_2[][] base){
		for (BinaryOperation_3_2[] row: base){
			for (BinaryOperation_3_2 operation:row){
				if (operation != null ){
					System.out.print(operation.asString()+"   ");
				}
			}
			System.out.println();
		}
	}
	public void saveCSVBase(BinaryOperation_3_2[][] base, String fileName){
		File wfile = new File(fileName+"_base"+".txt");
		Writer out;
		try{
			out = new FileWriter(wfile, true);
			for (BinaryOperation_3_2[] row: base){
				for (BinaryOperation_3_2 operation:row){
					if (operation != null ){
						out.write(operation.toString()+",");
					}
				}
				out.write("\n");			
			}
			out.flush();
			out.close();
		}
		catch(IOException e){
			System.out.println("ERROR: "+e);
		}
	}
	
	/* 下面的方法没有使用类BinaryOperation
	int[][] generateOperationBase(){
		int[][]base = new int[UPPER+1][UPPER+1]; 
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i+j<=UPPER){     // 更好的办法：初始化为-1
					base[i][j]=i+j;
				}else{
					base[i][j]= i+j-UPPER;
				}
				// System.out.print(base[i][j]+"\t");
			}
			// System.out.println();
		}
		return base;	
	}
	int[][] generateAdditionBase(){
		int[][]addbase = new int[UPPER+1][UPPER+1]; 
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (i+j<=UPPER){     // 更好的办法：初始化为-1
					addbase[i][j]=i+j;
					System.out.print(addbase[i][j]+"\t");
				}else{
					addbase[i][j]= -1;
				}
			}
			System.out.println();
		}
		return addbase;	
	}
	int[][] generateSubstractBase(){
		int[][]addbase = new int[UPPER+1][UPPER+1]; 
		for(int i=0; i<=UPPER; i++){
			for (int j=0; j<=UPPER; j++){
				if (j >= i){     // 更好的办法：初始化为-1
					addbase[i][j]=j-i;
					System.out.print(addbase[i][j]+"\t");
				}else{
					addbase[i][j]= -1;
				}
			}
			System.out.println();
		}
		return addbase;	
	}
	public void displayBase(int[][] base){
		for (int[] row: base){
			for (int operation:row){
				if (operation >=0){
					System.out.print(operation+"\t");
				}
			}
			System.out.println();
		}
	}
	*/
}
